#include "mainwindow.h"
#include <QMenuBar>
#include <QFileDialog>
#include <QString>
#include <QTextDocument>
#include <QDesktopServices>
#include <QDebug>

#include <QSplitter>
#include <QTreeView>
#include <QTextEdit>
#include <QFileSystemModel>
#include <QInputDialog>
#include <QTableView>
#include <QMessageBox>
#include <QProcess>
#include "booktablemodel.h"

/**
 * @brief 构造函数，执行窗口的构建
 * @param parent
 */
MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent) {
    resize(600, 200);
    setWindowTitle(tr("Paper Peer (under development)"));
    setupLayout();
    createActions();  // |createActions| depend on pointers created during |setupLayout()|
    createMenus();    // So does |createMenus| relies on |createActions|
    pwd = new QDir(QDir::homePath());
}

MainWindow::~MainWindow() {
}

/**
 * @brief 生成Actions
 */
void MainWindow::createActions() {
    openTeXFileAction = new QAction(tr("打开BibTeX文件"));
    QObject::connect(openTeXFileAction, SIGNAL(triggered()), this, SLOT(openFile()));

    openPdfAction = new QAction(tr("打开PDF文件"));
    QObject::connect(openPdfAction, SIGNAL(triggered()), this, SLOT(viewPdf()));

    openDoiUrlAction = new QAction(tr("打开原文链接（依据doi）"));
    QObject::connect(openDoiUrlAction, SIGNAL(triggered()), this, SLOT(openDoiUrl()));

    QObject::connect(tableView, SIGNAL(clicked(const QModelIndex &)), this, SLOT(onTableClicked(const QModelIndex &)));
    createLibAction = new QAction(tr("图书馆"));
    QObject::connect(createLibAction, SIGNAL(triggered()), this, SLOT(createLib()));

    importPdfAction = new QAction(tr("导入PDF文件"));
    QObject::connect(importPdfAction, SIGNAL(triggered()), this, SLOT(importPdf()));

    addBibItemAction = new QAction(tr("添加条目"));
    QObject::connect(addBibItemAction , SIGNAL(triggered()), this, SLOT(addBibItem()));

    exportListAction = new QAction(tr("导出bib文件到图书馆"));
    QObject::connect(exportListAction , SIGNAL(triggered()), this, SLOT(exportList()));

    deleteItemAction = new QAction(tr("删除条目"));
    QObject::connect(deleteItemAction , SIGNAL(triggered()), this, SLOT(deleteItem()));

    revealInExplorerAction = new QAction(tr("在文件管理器中打开图书馆"));
    QObject::connect(revealInExplorerAction , SIGNAL(triggered()), this, SLOT(revealInExplorer()));
}

/**
 * @brief 生成菜单栏
 */
void MainWindow::createMenus() {

    this->fileMenu = menuBar()->addMenu(tr("文件"));
    QMenu *menuCreate = new QMenu(tr("新建"));
    menuCreate->addAction(createLibAction);
    fileMenu->addMenu(menuCreate);
    fileMenu->addAction(openTeXFileAction);
    fileMenu->addAction(deleteItemAction);
    fileMenu->addAction(revealInExplorerAction);

    this->importMenu = menuBar()->addMenu(tr("导入"));
    importMenu->addAction(importPdfAction);
    importMenu->addAction(addBibItemAction);

    this->exportMenu = menuBar()->addMenu(tr("导出"));
    exportMenu->addAction(exportListAction);

    this->viewMenu = menuBar()->addMenu(tr("阅览"));
    viewMenu->addAction(openPdfAction);
    viewMenu->addAction(openDoiUrlAction);
}

/**
 * @brief 构建窗口布局
 */
void MainWindow::setupLayout() {
    mainSplitter = new QSplitter(Qt::Horizontal, nullptr);
    leftSplitter = new QSplitter(Qt::Vertical, mainSplitter);
    tableView = new QTableView(mainSplitter);
    rightSplitter = new QSplitter(Qt::Vertical, mainSplitter);

    QFileSystemModel *fsmodel = new QFileSystemModel();
    fsmodel->setRootPath(QDir::currentPath());
    treeView = new QTreeView(leftSplitter);

    treeView->setModel(fsmodel);
    leftSplitter->setSizes({2000, 100});

    rightSplitter->setOpaqueResize(true);

    detail = new QTextEdit(rightSplitter);
    detail->setMarkdown("# Hello, World!");
    detail->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Maximum);

    mainSplitter->setSizes({100, 300, 100});
    mainSplitter->show();
    mainSplitter->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Maximum);

    setCentralWidget(mainSplitter);
}

/**
 * @brief 生成表格内容
 * @param s
 */
void MainWindow::setTableContent(QString const & s) {
    bookModel = new BookTableModel(s, mainSplitter);
    tableView->setModel(bookModel);
}

/**
 * @brief 槽函数，打开文件
 */
void MainWindow::openFile()
{
    QString fileName = QFileDialog::getOpenFileName(this, tr("选择BibTeX文件"), QString(), tr("*.bib"));
    qDebug() << fileName;
    QFile f(fileName);
    f.open(QFile::ReadOnly);
    QString buf = f.readAll().simplified();
    this->setTableContent(buf);
}

/**
 * @brief 槽函数，打开当前选中条目的PDF文件；若没有PDF文件，报错。
 */
void MainWindow::viewPdf() const {
    // TODO: filePath as parameter
    QString currentFileName = bookModel->list.at(currentRow, "title").left(64) + ".pdf";
    QString fileUrl = "file:///" + pwd->absolutePath() + "/" + currentFileName;
    bool is_open = QDesktopServices::openUrl(fileUrl);
    qDebug() << is_open;
}

/**
 * @brief 槽函数，根据当前选中条目的doi，打开文献来源网站
 */
void MainWindow::openDoiUrl() const {
    QString const doi = bookModel->list.at(currentRow, "doi");
    QString doiUrl = "https://doi.org/" + doi;
    bool is_open = QDesktopServices::openUrl(doiUrl);
    qDebug() << is_open;
}

/**
 * @brief 槽函数，点击表格响应事件
 * @param index: 被点击的条目的坐标
 */
void MainWindow::onTableClicked(QModelIndex const & index) {
    qDebug() << index;
    currentRow = index.row();
    currentColumn = index.column();

    QString desc =
        " <span style=\"font-size: 14px\"><b>%1</b></span> \n"
        " ## Author: %2 \n\n"
        " ### %3, %4 \n "
        "------- \n"
        " <span style=\"font-size: 14px\">%5</span> \n";
    bibItem current = bookModel->list.at(currentRow);
    desc = desc.arg(current["title"], current["author"], current["year"], current["month"], current["abstract"]);
    detail->setMarkdown(desc);
}

/**
 * @brief 选中文件夹作为图书馆
 */
void MainWindow::createLib() {
    QString dirName = QFileDialog::getExistingDirectory(this);
    pwd = new QDir(dirName);
    this->setWindowTitle("Paper Peer -- " + pwd->dirName());
}

/**
 * @brief 选择PDF文件，复制到当前图书馆中
 */
void MainWindow::importPdf() {
    QString filePathName = QFileDialog::getOpenFileName(this);
    QString fileName = filePathName.split('/').back();
    QString newFileName = bookModel->list.at(currentRow, "title").left(64) + ".pdf";
    QFile f(filePathName);
    QString destPath = pwd->absolutePath() + "/" + newFileName;  // TODO: 重命名
    bool is_ok = f.copy(destPath);
    qDebug() << is_ok;
}

/**
 * @brief 槽函数，添加一个bib条目
 */
void MainWindow::addBibItem() {
    bool is_ok;
    QString bibText = QInputDialog::getMultiLineText(this, "请输入bib引文", "Bib", "", &is_ok).simplified();
    qDebug() << is_ok;
    if(is_ok) {
        qDebug() << bibText;
        bookModel->addItem(bibText);
    }
}

/**
 * @brief 槽函数，导出bib文件
 */
void MainWindow::exportList() {
    QFile bibFile(pwd->absolutePath().append("/main.bib"));
    QString bibStr = bookModel->list.toString();
    bool yes = false;
    if(not bibFile.exists()) {
        yes = true;
    }
    else {
        switch(QMessageBox::warning(
                   this, tr("提示"), tr("main.bib已存在，覆盖？"),
                   QMessageBox::Yes | QMessageBox::No, QMessageBox::No
                   )) {
        case QMessageBox::Yes:
            yes = true;
        case QMessageBox::No:
        default:
            break;
        }
    }
    if(yes) {
        bibFile.open(QFile::WriteOnly);
        bibFile.write(bibStr.toStdString().data());
        bibFile.close();
    }
}

/**
 * @brief 槽函数，删除bib条目。删除前会弹出警告对话框。
 */
void MainWindow::deleteItem() {
    QString currentTitle = bookModel->list.at(currentRow, "title");
    switch(QMessageBox::warning(
               this, tr("提示"), tr(QString("确定删除%1?").arg(currentTitle).toStdString().c_str()),
               QMessageBox::Yes | QMessageBox::No, QMessageBox::No
               )) {
    case QMessageBox::Yes:
        bookModel->erase(currentRow);
        break;
    case QMessageBox::No:
    default:
        break;
    }
}

void MainWindow::revealInExplorer() const {
    bool is_ok = QDesktopServices::openUrl(QUrl::fromLocalFile(pwd->absolutePath()));
    qDebug() << is_ok;
}
